package com.wan37.logic.utils;

import com.wan37.common.xml.XMLUtils;
import org.dom4j.Attribute;
import org.dom4j.Element;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 反射实现xml到实体工具
 *
 * @author : luoyong
 * @date : 2020-06-15 21:21
 **/
@Component
public class XmlUtil<T> {

    /**
     * 获取xml中的key和value反射注入到实体中
     *
     * @param path
     * @param clazz
     * @return
     */
    public List<T> getXmlFileValues(String path, Class clazz) {
        List<T> list = new LinkedList<>();
        Map<String, Class<?>[]> parameterMap = new HashMap<>();
        try {
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                parameterMap.put(method.getName(), method.getParameterTypes());
            }
            //获取到根标签
            Element root = XMLUtils.parseXmlFile(path);
            //子标签
            Iterator it1 = root.elementIterator();
            while (it1.hasNext()) {
                T t = (T) clazz.getConstructor().newInstance();
                Element object1 = (Element) it1.next();
                List<Attribute> attributes = object1.attributes();
                for (Attribute attribute : attributes) {
                    String s = fieldToMethodSet(attribute.getName());
                    Method method = clazz.getMethod(s, parameterMap.get(s));
                    method.invoke(t, attribute.getValue());
                }
                Iterator it2 = object1.elementIterator();
                while (it2.hasNext()) {
                    String s = "numberMap";
                    Element object2 = (Element) it2.next();
                    //如果是数值就入map处理
                    if (s.equals(object2.getName())) {
                        String s1 = fieldToMethodGet(object2.getName());
                        Method method = clazz.getMethod(s1, parameterMap.get(s1));
                        Map<String, Long> map = (Map<String, Long>) method.invoke(t);
                        Iterator it3 = object2.elementIterator();
                        while (it3.hasNext()) {
                            Element object3 = (Element) it3.next();
                            map.put(object3.getName(), Long.parseLong(object3.getStringValue()));
                        }
                    }
                    String s2 = fieldToMethodSet(object2.getName());
                    Method method = clazz.getMethod(s2, parameterMap.get(s2));
                    String parameterType = method.getParameterTypes()[0].getSimpleName();
                    //判断反射调用参数的类型
                    if ("String".equals(parameterType)) {
                        method.invoke(t, object2.getStringValue());
                    } else if ("Long".equals(parameterType) || "long".equals(parameterType)) {
                        method.invoke(t, Long.parseLong(object2.getStringValue()));
                    } else if ("Integer".equals(parameterType) || "int".equals(parameterType)) {
                        method.invoke(t, Integer.parseInt(object2.getStringValue()));
                    } else if ("Float".equals(parameterType) || "float".equals(parameterType)) {
                        method.invoke(t, Float.parseFloat(object2.getStringValue()));
                    } else if ("AtomicLong".equals(parameterType)){
                        method.invoke(t, Long.parseLong(object2.getStringValue()));
                    }
                }
                //添加到实体集合中
                list.add(t);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 属性转换为set方法
     *
     * @param s
     * @return
     */
    public String fieldToMethodSet(String s) {
        return "set" + s.substring(0, 1).toUpperCase() + s.substring(1);
    }

    /**
     * 属性转换为get方法
     *
     * @param s
     * @return
     */
    public String fieldToMethodGet(String s) {
        return "get" + s.substring(0, 1).toUpperCase() + s.substring(1);
    }


}
